package projetDames.composant;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.util.ArrayList;
import javax.swing.JPanel;

public class Dame extends Piece implements Commun {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private ArrayList<Pointp> miamMiam = new ArrayList<Pointp>();

	private transient Image image;
	private String urlImage;
	private final int largeurImage = 45; // largeur image
	private final int hauteurImage = 45; // hauteur image

	public Dame(boolean coul, int x, int y, Piece[][] plat) {
		super(coul, x, y, plat);
	}

	public void dessine(Graphics g, JPanel p, int x, int y) {

		if (super.couleur) {
			this.urlImage = "src/projetDames/images/piece/dameNoir.png";
		} else {
			this.urlImage = "src/projetDames/images/piece/dameBlanc.png";
		}
		this.image = Toolkit.getDefaultToolkit().getImage(urlImage); // on recup
		// l'image

		g.drawImage(image, x, y, largeurImage, hauteurImage, p);
	}

	/**
	 * Permet de savoir si il existe au moins un ennemi mangeable sur une
	 * diagonale donnee
	 * 
	 * @param diag
	 *            direction geographique de la diagonale
	 * @return vrai si il existe au moins un ennemi mangeable sur la diagonale
	 *         envoye en parametre, faux sinon
	 */
	public boolean mangerDansDiagonale(int diag) {
		boolean rep = false;
		Pointp tmpP = this.initialisePoint(diag);

		while (tmpP.dansBornes() && super.plateau[tmpP.x][tmpP.y] == null) {
			tmpP = this.incrementePoint(tmpP, diag);
		}
		if (etat(tmpP) == _ENNEMI) {
			tmpP = this.incrementePoint(tmpP, diag);
			if (tmpP.dansBornes() && super.plateau[tmpP.x][tmpP.y] == null) {
				rep = true;
			}
		}
		return rep;
	}

	/**
	 * Permet de savoir pour chaque diagonale, si il existe au moins un ennemi
	 * mangeable
	 * 
	 * @return un tableau[4] de boolean avec pour chaque cases, vrai si un
	 *         ennemi est mangeable, faux sinon
	 */
	// renvoi un tableau de boolean avec pour chaque case vrai si un ennemi est
	// mangeable, faux sinon
	public boolean[] tabEnnemiMangeable() {
		boolean[] tab = { false, false, false, false };
		for (int i = 0; i < tab.length; i++) {
			tab[i] = this.mangerDansDiagonale(i);
		}
		return tab;
	}

	public ArrayList<ArrayList<Pointp>> listVoisins() {
		// tab[0] = diagonale haute gauche (x-1, y-1)
		// tab[1] = diagonale haute droite (x-1, y+1)
		// tab[2] = diagonale basse droite (x+1, y+1)
		// tab[3] = diagonale basse gauche (x+1, y-1)
		ArrayList<ArrayList<Pointp>> list = new ArrayList<ArrayList<Pointp>>();
		Pointp tmpP = new Pointp(0, 0);
		boolean[] tab = this.tabEnnemiMangeable();

		if (this.ennemiDansTab(tab)) {
			for (int i = 0; i < 4; i++) {
				list.add(new ArrayList<Pointp>());
				if (tab[i] == true) {// si la diagonale i possede un ennemi
										// mangeable
					tmpP = this.initialisePoint(i);
					while (tmpP.dansBornes()
							&& super.plateau[tmpP.x][tmpP.y] == null) {
						tmpP = this.incrementePoint(tmpP, i);
					}
					tmpP = this.incrementePoint(tmpP, i);
					while (tmpP.dansBornes()
							&& super.plateau[tmpP.x][tmpP.y] == null) {
						list.get(i).add(new Pointp(tmpP.x, tmpP.y));
						tmpP = this.incrementePoint(tmpP, i);
					}
				}
			}
		} else { // sinon c'est qu'il n'existe aucun ennemis mangeables, donc on
					// ajoute les 4 diagonales jusqu'a une case non-vide
			for (int i = 0; i < 4; i++) {
				tmpP = this.initialisePoint(i);
				list.add(new ArrayList<Pointp>());
				while (tmpP.dansBornes()
						&& super.plateau[tmpP.x][tmpP.y] == null) {
					list.get(i).add(new Pointp(tmpP.x, tmpP.y));
					tmpP = this.incrementePoint(tmpP, i);
				}
			}
		}
		return list;
	}

	// retourne vrai si il il y a au moins 1 ennemi dans le tableau de booleen
	// envoyé en paramètre
	public boolean ennemiDansTab(boolean[] tab) {
		int i = 0;
		while (i < tab.length && tab[i] == false) {
			i++;
		}
		return i < tab.length;
	}

	// les 4 methodes suivante permettre de retourner une liste de point pour un
	// diagonale jusqu'a une case non vide
	// public ArrayList<Pointp> addDiagHautGauche() {
	// ArrayList<Pointp> list = new ArrayList<Pointp>();
	// Pointp tmpP = new Pointp(this.xy.x-1, this.xy.y-1);
	// int i = 0;
	//		
	// while(i<4 && tmpP.dansBornes() && super.plateau[tmpP.x][tmpP.y] != null)
	// {
	// list.add(new Pointp(tmpP.x, tmpP.y));
	// tmpP.x -= 1; tmpP.y -= 1;
	// }
	// return list;
	// }
	//	
	// public ArrayList<Pointp> addDiagHautDroit() {
	// ArrayList<Pointp> list = new ArrayList<Pointp>();
	// Pointp tmpP = new Pointp(this.xy.x-1, this.xy.y+1);
	// int i = 0;
	//		
	// while(i<4 && tmpP.dansBornes() && super.plateau[tmpP.x][tmpP.y] != null)
	// {
	// list.add(new Pointp(tmpP.x, tmpP.y));
	// tmpP.x -= 1; tmpP.y += 1;
	// }
	// return list;
	// }
	//	
	// public ArrayList<Pointp> addDiagBasGauche() {
	// ArrayList<Pointp> list = new ArrayList<Pointp>();
	// Pointp tmpP = new Pointp(this.xy.x+1, this.xy.y-1);
	// int i = 0;
	//		
	// while(i<4 && tmpP.dansBornes() && super.plateau[tmpP.x][tmpP.y] != null)
	// {
	// list.add(new Pointp(tmpP.x, tmpP.y));
	// tmpP.x += 1; tmpP.y -= 1;
	// }
	// return list;
	// }
	//	
	// public ArrayList<Pointp> addDiagBasDroit() {
	// ArrayList<Pointp> list = new ArrayList<Pointp>();
	// Pointp tmpP = new Pointp(this.xy.x+1, this.xy.y+1);
	// int i = 0;
	//		
	// while(i<4 && tmpP.dansBornes() && super.plateau[tmpP.x][tmpP.y] != null)
	// {
	// list.add(new Pointp(tmpP.x, tmpP.y));
	// tmpP.x += 1; tmpP.y += 1;
	// }
	// return list;
	// }

	// retourne le point envoyé en parametre incrementé de 1
	public Pointp incrementePoint(Pointp p, int diagonale) {
		Pointp point = new Pointp(p.x, p.y);
		switch (diagonale) {
		case 0:
			point.x -= 1;
			point.y -= 1;
			break;
		case 1:
			point.x -= 1;
			point.y += 1;
			break;
		case 2:
			point.x += 1;
			point.y += 1;
			break;
		case 3:
			point.x += 1;
			point.y -= 1;
			break;
		}
		return point;
	}

	// retourne un Pointp initialisé
	public Pointp initialisePoint(int diagonale) {
		Pointp p;
		switch (diagonale) {
		case 0:
			p = new Pointp(super.xy.x - 1, super.xy.y - 1);
			break;
		case 1:
			p = new Pointp(super.xy.x - 1, super.xy.y + 1);
			break;
		case 2:
			p = new Pointp(super.xy.x + 1, super.xy.y + 1);
			break;
		case 3:
			p = new Pointp(super.xy.x + 1, super.xy.y - 1);
			break;
		default:
			p = new Pointp(0, 0);
		}
		return p;
	}

	/**
	 * Permet de calculer la case contenant la piece ennemi d'une diagonale
	 * pres-requis : get0 est la premiere valeur d'une diagonale contenant un
	 * ennemi
	 * 
	 * @param get0
	 *            premiere valeur d'une diagonale de Pointp contenant un ennemi
	 * @param diag
	 *            direction geographique de la diagonale
	 * @return les coordonnees d'une case contenant un ennemi
	 */
	private Pointp recupEnnemiDiag(Pointp get0, int diag) {
		Pointp ennemi;
		switch (diag) {
		case _NO:
			ennemi = new Pointp(get0.x + 1, get0.y + 1);
			break;
		case _NE:
			ennemi = new Pointp(get0.x + 1, get0.y - 1);
			break;
		case _SE:
			ennemi = new Pointp(get0.x - 1, get0.y - 1);
			break;
		case _SO:
			ennemi = new Pointp(get0.x - 1, get0.y + 1);
			break;
		default:
			System.out.println("ERREUR : Dame.recupEnnemiDiag");
			ennemi = new Pointp(-1, -1);
		}
		return ennemi;
	}

	/**
	 * Permet de savoir si il existe au moins un ennemi non mange sur les
	 * diagonale de la piece courante pres-requis : listDiag contient au moins
	 * un ennemi
	 * 
	 * @param listDiag
	 *            contient une liste des diagonale de la piece courante retourne
	 *            par listVoisins()
	 * @return vrai si au moins un ennemi n'est pas dans miamMiam, faux sinon
	 */
	public boolean existeEnnemiMangeable(ArrayList<ArrayList<Pointp>> listDiag) {
		int i = 0;
		int j = 0;
		boolean ennemiTrouve = false;
		while (i < 4 && !ennemiTrouve) {
			if (!listDiag.get(i).isEmpty()) { // si la diagonale n'est pas vide
				System.out.println("!empty"); // DEBUG
				// while(j<listDiag.get(i).size() && !ennemiTrouve) {
				System.out.println(this.recupEnnemiDiag(listDiag.get(i).get(0),
						i)); // DEBUG
				if (!this.listPointContient(this.recupEnnemiDiag(listDiag
						.get(i).get(0), i), this.miamMiam)) { // si l'ennemi
																// recupere n'a
																// pas ete mange
																// (donc dans
																// miamMiam)
					ennemiTrouve = true;
					System.out.println("ennemiTrouve");
				}
				// j++;
				// }
			}
			i++;
		}
		return ennemiTrouve;
	}

	@Override
	public Pointp[] trouverVoisin(Pointp p) {

		return null;
	}

	@Override
	public void meilleurChemin(Pointp p, int rang) {
		ArrayList<ArrayList<Pointp>> listdiag = this.listVoisins();

		cheminCourant.add(p);
		System.out.println("point: " + p);

		if (this.existeEnnemiMangeable(listdiag)) {
			for (int i = 0; i < 4; i++) { // on scanne chaque diagonale
				if (!listdiag.get(i).isEmpty()) { // si la diagonale n'est pas
													// vide
					// on retrouve la piece mangee, et on l'ajoute a miamMiam
					Pointp pointEnnemi = this.recupEnnemiDiag(listdiag.get(i)
							.get(0), i);
					for (int j = 0; j < listdiag.get(i).size(); j++) { // on
																		// parcours
																		// toutes
																		// les
																		// cases
																		// de la
																		// diagonale
						this.miamMiam.add(pointEnnemi);
						meilleurChemin(listdiag.get(i).get(j), rang + 1);
						this.miamMiam.remove(this.miamMiam.size() - 1);
						this.cheminCourant
								.remove(this.cheminCourant.size() - 1);
					}
				}
			}
		} else {
			if (rang == 0) {
				for (ArrayList<Pointp> diag : listdiag) {
					super.addList(diag);
				}
			} else {
				if (this.cheminCourant.size() >= tailleMeilleurChemin) {
					if (this.cheminCourant.size() > tailleMeilleurChemin) {
						super.clearList();
						super.setTailleMeilleurChemin(cheminCourant.size());
					}
					super.addList(cheminCourant);
					System.out.println(meilleurChemin); // DEBUG
					this.addPionsManges(miamMiam);
					System.out.println("pions manges: " + miamMiam); // DEBUG
				}
			}
		}
	}
}
